package com.kingbook.core.base;

import com.alibaba.fastjson.JSONObject;
import com.kingbook.core.exception.DatabaseAccessException;
import com.kingbook.core.executor.DatabaseOperations;
import com.kingbook.core.result.JSONPageResult;
import com.kingbook.core.result.JSONResult;
import com.kingbook.core.sql.SqlContext;
import com.kingbook.core.sql.SqlFactory;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * @Author: Bucky
 * @Date: 2019/1/2
 * @Version 1.0
 */
public abstract class BaseService {

    @Resource
    private DatabaseOperations operations;

    private String namespace = "";

    private final String pageNo = "pageNo";

    private final String pageSize = "pageSize";

    private static String errMsg = "数据处理异常";

    protected int getRows(Map<String, ?> param) {
        int i = 0;
        try {
            JSONResult js = find("getRows", param);
            if (js.isSuccess()) {
                i = Integer.parseInt(js.getDataElement("count"));
            }
        } catch (Exception e) {
        }
        return i;
    }

    /**
     * 返回第一条结果
     *
     * @param sqlId
     * @param param
     * @return
     */
    protected Map<String, Object> findMap(String sqlId, Map<String, ?> param) {
        return findObject(sqlId, param, Map.class);
    }

    /**
     * 返回第一条结果
     *
     * @param sqlId
     * @param param
     * @return
     */
    protected JSONResult find(String sqlId, Map<String, ?> param) {
        return JSONResult.success(findObject(sqlId, param, JSONObject.class));
    }

    /**
     * 返回第一条结果
     *
     * @param sqlId
     * @param param
     * @return
     */
    protected <T> T findObject(String sqlId, Map<String, ?> param, Class<T> clazz) {
        return operations.findFirst(sqlContext(sqlId, param), clazz);
    }

    //////////////////////////////////////////////////////////////////////////////


    protected Map<String, Object>[] queryMap(String sqlId, Map<String, ?> param) {
        return operations.queryMap(sqlContext(sqlId, param));
    }

    protected JSONResult query(String sqlId, Map<String, ?> param) {
        try {
            return operations.query(sqlContext(sqlId, param));
        } catch (DatabaseAccessException e) {
            return JSONResult.failed(errMsg);
        }
    }

    protected <T> List<T> queryList(String sqlId, Map<String, ?> param, Class<T> clazz) {
        return operations.query(sqlContext(sqlId, param), clazz);
    }

    //////////////////////////////////////////////////////////////////////////////

    /**
     * 具有分页功能的查询
     */

    protected JSONPageResult queryForPages(String sqlId, String cSqlId, Map<String, ?> param) {
        return queryForPages(sqlId, cSqlId, param, null);
    }

    protected JSONPageResult queryForPages(String sqlId, String cSqlId, Map<String, ?> param, Class clazz) {
        if (!param.containsKey(pageNo) || !param.containsKey(pageSize)) {
            return JSONPageResult.failed("分页查询缺少pageNo或pageSize参数 ");
        }
        int index, size;
        try {
            index = (Integer) param.get(pageNo);
        } catch (Exception e) {
            index = Integer.parseInt((String) param.get(pageNo));
        }
        try {
            size = (Integer) param.get(pageSize);
        } catch (Exception e) {
            size = Integer.parseInt((String) param.get(pageSize));
        }
        try {
            size = Math.min(size, 1000);
            sqlId = sqlId.contains(".") ? sqlId : namespace + "." + sqlId;
            cSqlId = cSqlId.contains(".") ? cSqlId : namespace + "." + cSqlId;
            return operations.queryForPages(SqlFactory.getSqlPageContext(sqlId, param, cSqlId, param, index, size, operations.getDBDialect()), clazz);
        } catch (DatabaseAccessException e) {
            return JSONPageResult.failed(errMsg);
        }
    }

    protected int getRows(String sqlId, Map<String, ?> param) {
        try {
            return operations.getRows(sqlContext(sqlId, param));
        } catch (DatabaseAccessException e) {
            return 0;
        }
    }

    //////////////////////////////////////////////////////////////////////////////
    protected JSONResult insert(String sqlId, Map<String, ?> param) {
        return operations.update(sqlContext(sqlId, param));
    }

    protected JSONResult insertReturnKey(String sqlId, Map<String, ?> param) {
        return operations.insertReturnKey(sqlContext(sqlId, param));
    }

    //////////////////////////////////////////////////////////////////////////////
    protected JSONResult update(String sqlId, Map<String, ?> param) {
        return operations.update(sqlContext(sqlId, param));
    }

    //////////////////////////////////////////////////////////////////////////////
    protected JSONResult delete(String sqlId, Map<String, ?> param) {
        return operations.update(sqlContext(sqlId, param));
    }

    //////////////////////////////////////////////////////////////////////////////
    protected JSONResult batchUpdate(String sqlId, List<Map<String, ?>> batchValues) {
        return operations.batchUpdate(sqlContext(sqlId, batchValues.get(0)), batchValues);
    }

    protected JSONResult batchUpdate(String sqlId, Map<String, ?>[] batchValues) {
        return operations.batchUpdate(sqlContext(sqlId, batchValues[0]), batchValues);
    }

    protected JSONResult batchInsertReturnKey(String sqlId, List<Map<String, ?>> batchValues) {
        return operations.batchInsertReturnKey(sqlContext(sqlId, batchValues.get(0)), batchValues);
    }

    protected JSONResult batchInsertReturnKey(String sqlId, Map<String, ?>[] batchValues) {
        return operations.batchInsertReturnKey(sqlContext(sqlId, batchValues[0]), batchValues);
    }

    /**
     * 查询序列，仅适用于Oracle数据库
     *
     * @param sequenceName
     * @return
     */
    protected Long nextSequence(String sequenceName) {
        return operations.findFirst(SqlFactory.getSqlContext("select " + sequenceName + ".nextval from dual", operations.getDBDialect(), null), Long.class);
    }
    ///////////////////////////////////////////////////////////////////////////

    private SqlContext sqlContext(String sqlId, Map<String, ?> param) {
        sqlId = sqlId.contains(".") ? sqlId : namespace + "." + sqlId;
        return SqlFactory.getSqlContext(sqlId, param, operations.getDBDialect());
    }

    protected void setNamespace(String namespace) {
        this.namespace = namespace;
    }
}
